﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading;
using Common.Utilities;
using Common.Utilities.Dispatcher;

namespace Workflows.Components.TextMining.Ontologies
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class TermRelationWorker: IWorker 
    {
        #region Implementation of IWorker

        public event WorkerStarted WorkerStartedEvent;
        public event WorkerFinished WorkerFinishedEvent;
        public event WorkerHasError WorkerErredEvent;
        public event WorkerCancelled WorkerCancelledEvent;
        public event WorkerStatusChanged WorkerStatusChangedEvent;

        private Thread workerThread;
        private TermRelationInstruction instruction;
        private TermRelationOutput output;
        private RunContext _Context;
        private Guid _TicketID;
        private string _WorkflowName;
        private string _ComponentName;

        /// <summary>
        /// 
        /// </summary>
        public string ComponentName
        {
            get { return _ComponentName; }
        }

        /// <summary>
        /// 
        /// </summary>
        public string WorkflowName
        {
            get { return _WorkflowName; }
        }

        /// <summary></summary>
        public Thread WorkerThread
        {
            get { return workerThread; }
        }
        /// <summary></summary>
        public InstructionBase Instruction
        {
            get { return instruction; }
        }
        /// <summary></summary>
        public ResultBase Output
        {
            get { return output; }
        }
        /// <summary></summary>
        public Type ComponentType
        {
            get { return typeof(TermRelationComponent); }
        }
        /// <summary></summary>
        public RunContext Context
        {
            get { return _Context; }
            set { _Context = value; }
        }
        /// <summary></summary>
        public void SetInstruction(Guid ticketGuid, InstructionBase request, string workflowName, string componentName)
        {
            this._TicketID = ticketGuid;
            this.instruction = (TermRelationInstruction)request;
            this._WorkflowName = workflowName;
            this._ComponentName = componentName;
        }
        /// <summary></summary>
        public void SetInstruction(RunContext context, Guid ticketGuid, InstructionBase request, string workflowName, string componentName)
        {
            this._TicketID = ticketGuid;
            this.instruction = (TermRelationInstruction)request;
            this._Context = context;
            this._WorkflowName = workflowName;
            this._ComponentName = componentName;
        }
        /// <summary></summary>
        public void DoWork()
        {
            if (this.WorkerStartedEvent != null)
            {
                this.WorkerStartedEvent(this._TicketID, this, this.GetType(), this.instruction);
            }
            this.workerThread = Thread.CurrentThread;
            this.BuildTermRelations();
        }
        /// <summary></summary>
        public void DoWorkAsync()
        {
            if (this.WorkerStartedEvent != null)
            {
                this.WorkerStartedEvent(this._TicketID, this, this.GetType(), this.instruction);
            }
            this.workerThread = new Thread(new ThreadStart(this.BuildTermRelations));
            this.workerThread.Start();
        }
        /// <summary></summary>
        public void CancelWork()
        {
            if (this.workerThread != null && this.workerThread.IsAlive)
            {
                this.workerThread.Abort();
                this.workerThread.Join();

                if (this.WorkerCancelledEvent != null)
                {
                    this.WorkerCancelledEvent(this._TicketID, this.GetType(), this.instruction);
                }
            }
        }

        #endregion

        #region work
        private void BuildTermRelations()
        {
            SqlConnection srcConn=new SqlConnection(this.instruction.ConnStr);
            SqlConnection tgtConn=new SqlConnection(this.instruction.TermRelationConnStr);
            try
            {
                srcConn.Open();
                SqlCommand srcCmd = srcConn.CreateCommand();
                string ftSearchSql = @"
SELECT
	Id, ColumnA, ColumnB
FROM
	CONTAINSTABLE({$FtTable}, ({$TxtField}), '') C
	INNER JOIN SampleTable ST ON
	ST.Id = C.[Key];
";
                tgtConn.Open();
            }
            catch (Exception ex)
            {
                if (this.WorkerErredEvent != null)
                    this.WorkerErredEvent(this._TicketID, this.GetType(), this.instruction, ex.ToString(), true);
            }
            finally
            {
                srcConn.Close();
                tgtConn.Close();
            }
        }
        #endregion

        #region doc-doc distances 
        private void GetDocNeighbors(SqlConnection srcConn, int docID, 
            ref List<int> neighborIDs, int maxNeighbors, 
            double docDistanceThreshold)
        {
            
        }

        private void CalculateDocDocDistances(SqlConnection srcConn, List<int> docIDs, 
            ref Dictionary<int, Dictionary<int, double>> docDocDistances)
        {
            
        }
        #endregion

        #region term weights
        private void CalculateTermWeights(SqlConnection srcConn, List<int> docIDs, 
            ref Dictionary<int, Dictionary<int, double>> termDocWeights)
        {
            
        }
        #endregion

        #region term distances 
        private void CalculateTermDistances(Dictionary<int, List<int>> termDocFreqs, 
            Dictionary<int, Dictionary<int,double>> termDocWeights,
            ref Dictionary<int, Dictionary<int, double>> termTermDistances)
        {
            
        }
        #endregion

        #region save term relations 
        private void SaveTermRelations(SqlConnection tgtConn, Dictionary<int,List<int>> termDocFreqs, Dictionary<int,Dictionary<int,double>> termTermDistances)
        {
            
        }
        #endregion
    }
}
